package cn.getech.data.development.utils.shell;

import cn.getech.data.development.utils.MysqlToHiveTypeConvertUtil;
import cn.getech.data.intelligence.common.exception.RRException;
import cn.getech.data.intelligence.common.utils.DateUtils;
import com.jcraft.jsch.*;
import org.apache.derby.iapi.services.io.ArrayInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Properties;

/**
 * @description: 类描述
 * @author: wangzhaowen：kiss
 * @create: 2020/9/27 11:21
 * @version: 2020/9/27
 **/
public class ExecuteShellUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(ExecuteShellUtil.class);

    /**
     * 未调用初始化方法 错误提示信息
     */
    private static final String DONOT_INIT_ERROR_MSG = "please invoke init(...) first!";

    private Session session;

    private Channel channel;

    private ChannelExec channelExec;
    private ChannelSftp sftp = null;

    private ExecuteShellUtil() {
    }

    /**
     * 获取ExecuteShellUtil类实例对象
     *
     * @return 实例
     * @date 2019/4/29 16:58
     */
    public static ExecuteShellUtil getInstance() {
        return new ExecuteShellUtil();
    }

    /**
     * 初始化
     *
     * @param ip       远程Linux地址
     * @param port     端口
     * @param username 用户名
     * @param password 密码
     * @throws JSchException JSch异常
     * @date 2019/3/15 12:41
     */
    public void init(String ip, Integer port, String username, String password) throws JSchException {
        JSch jsch = new JSch();
        jsch.getSession(username, ip, port);
        session = jsch.getSession(username, ip, port);
        session.setPassword(password);
        Properties sshConfig = new Properties();
        sshConfig.put("StrictHostKeyChecking", "no");
        session.setConfig(sshConfig);
        session.connect(60 * 1000);
        LOGGER.info("Session connected!");
        // 打开执行shell指令的通道
        channel = session.openChannel("exec");
        channelExec = (ChannelExec) channel;
        Channel channel = session.openChannel("sftp");
        channel.connect();
        sftp = (ChannelSftp) channel;
    }

    /**
     * 执行一条命令
     */
    public void execCmd(String command) throws Exception {
        if (session == null || channel == null || channelExec == null) {
            throw new Exception(DONOT_INIT_ERROR_MSG);
        }
        LOGGER.info("execCmd command - > {}", command);
        channelExec.setCommand(command);
        channel.setInputStream(null);
        channelExec.setErrStream(System.err);
        channel.connect();
    }

    /**
     * 释放资源
     *
     * @date 2019/3/15 12:47
     */
    public void close() {
        if (channelExec != null && channelExec.isConnected()) {
            channelExec.disconnect();
        }
        if (channel != null && channel.isConnected()) {
            channel.disconnect();
        }
        if (session != null && session.isConnected()) {
            session.disconnect();
        }
        if (sftp != null) {
            sftp.disconnect();
            if (null != sftp) {
                sftp.quit();
            }
        }
    }

    /**
     * 上传文件
     */
    public void uploadFile(String content, String fileName) throws Exception {

        InputStream inputStream = null;
        try {
            inputStream = new ArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
            sftp.setInputStream(inputStream);
            String path = fileName.substring(0, fileName.lastIndexOf("/"));
            try {
                sftp.mkdir(path);
            } catch (SftpException e) {
                LOGGER.warn("{}创建异常", path);
            }
            sftp.put(inputStream, fileName);
        } catch (Exception e) {
            LOGGER.warn("创建异常:", e);
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }
    }

    /**
     * 上传文件
     */
    public void uploadFile(String content, String fileName,Integer node) throws Exception {

        InputStream inputStream = null;
        try {
            inputStream = new ArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
            sftp.setInputStream(inputStream);
            String path = fileName.substring(0, fileName.lastIndexOf("/"));
            try {
                sftp.mkdir(path);
            } catch (SftpException e) {
                LOGGER.warn("{}创建异常", path);
            }
            sftp.put(inputStream, fileName,node);
        } catch (Exception e) {
            LOGGER.warn("创建异常:", e);
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }
    }

    // 从 服务器 获取 数据
    public String getFile(String filePath) {

        StringBuffer buffer = new StringBuffer();
        try {
            String fileAndLog = getFileLog(filePath);
            return fileAndLog;
        } catch (Exception e) {
            LOGGER.error("获取文件失败:{},{}", filePath, e.getMessage());
        }
        return buffer.toString();
    }


    public String getFileLog(String filePath) throws Exception {
        StringBuffer buffer = new StringBuffer();
        InputStream inputStream = null;
        BufferedReader in = null;
        try {
            //获取生成文件流
            inputStream = sftp.get(filePath);
            in = new BufferedReader(new InputStreamReader(inputStream,StandardCharsets.UTF_8));
            String line = "";
            while ((line = in.readLine()) != null && buffer.length() < 200000) {
                buffer.append(line);
                buffer.append("\n");
            }
            //关闭流
            inputStream.close();
            in.close();

        } catch (IOException | SftpException e) {
            LOGGER.error("获取文件失败:{},{}", filePath, e.getMessage());
            throw new RRException("get log fail:" + filePath + "," + e.getMessage());
        } finally {
            if(null != inputStream){
                inputStream.close();
            }
            if(null != in){
                in.close();
            }
        }
        return buffer.toString();
    }



    public static void main(String[] args) throws JSchException {
        try {
            ExecuteShellUtil resShell = ExecuteShellUtil.getInstance();
            resShell.init("cdh-hadoop-1",
                    22, "hdfs", "hdfs@123");
            String res=resShell.getFile("/usr/realtime/flink_sql/flinktask_98_20201216_14_54_41.log");
            if (res.length() > 100000) {
                res = res.substring(0, 100000);
            }
            res = new String(res.getBytes(StandardCharsets.UTF_8));
            resShell.close();
            System.out.println(res);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}